package top.wecreate.snet;

/**
 * Snet 的 配置类。可以配置基本的请求参数信息，比如编码格式，是否重定向等
 * 
 * @author dell
 * 
 */
public class SnetConfig {
	/**
	 * 当前Snet的版本信息
	 */
	public static final String SNET_VERSION = "1.0_2015-12-17_11:05";
	/**
	 * 网络超时时间
	 */
	public static final int TIME_OUT = 5000;
	/**
	 * 是否支持网络重定向
	 */
	public static final boolean FOLLOW_REDIRECTS = true;
	/**
	 * 是否使用用户缓存
	 */
	public static final boolean USE_CACHES = false;
	/**
	 * 是否使用本地测试数据
	 */
	public static final boolean USE_LOCAL_TEST = false;

	/**
	 * 编码格式
	 */
	public static final String CHAR_SET = "UTF-8";

	private static SnetConfig instance;

	// 以下变量和Builder中的变量对应
	private String charSet;
	private String userAgent;
	private int connectionTimeout;
	private int readTimeout;
	private boolean useCaches;
	private boolean followRedirects;
	private boolean isUseLocalTest;

	private SnetConfig(SnetConfigBuilder builder) {
		this.charSet = builder.charSet;
		this.userAgent = builder.userAgent;
		this.connectionTimeout = builder.connectionTimeout;
		this.readTimeout = builder.readTimeout;
		this.useCaches = builder.useCaches;
		this.followRedirects = builder.followRedirects;
		this.isUseLocalTest = builder.useLocalTest;
	}

	/**
	 * 初始化Snet。建议在Application中调用此方法。
	 * 
	 * @param builder
	 */
	public static void init(SnetConfigBuilder builder) {
		if (instance == null) {
			synchronized (SnetConfig.class) {
				if (instance == null) {
					instance = new SnetConfig(builder);
				}
			}
		}
	}

	/**
	 * 初始化完毕之后，通过此方法获取对应的配置信息。 <br>
	 * 如果没有初始化，将抛出IllegalStateException。
	 * 
	 * @return
	 */
	public static SnetConfig getInstance() {
		if (instance == null) {
			throw new IllegalStateException("Snet 还没有被初始化");
		}
		return instance;
	}

	/**
	 * 获取User-Agent
	 * 
	 * @return
	 */
	public String getUserAgent() {
		return userAgent;
	}

	/**
	 * 获取连接超时时间
	 * 
	 * @return 毫秒
	 */
	public int getConnectionTimeout() {
		return connectionTimeout;
	}

	/**
	 * 获取读取超时时间
	 * 
	 * @return 毫秒
	 */
	public int getReadTimeout() {
		return readTimeout;
	}

	/**
	 * 是否使用缓存
	 * 
	 * @return
	 */
	public boolean isUseCaches() {
		return useCaches;
	}

	/**
	 * 是否支持重定向
	 * 
	 * @return
	 */
	public boolean isFollowRedirects() {
		return followRedirects;
	}

	/**
	 * 获取编码格式
	 * 
	 * @return
	 */
	public String getCharSet() {
		return charSet;
	}

	/**
	 * 是否使用本地测试数据
	 * 
	 * @return
	 */
	public boolean isUseLocalTest() {
		return isUseLocalTest;
	}

	/**
	 * 配置构造器。用于设置基本的请求信息。
	 * 
	 * @author dell
	 * 
	 */
	public static class SnetConfigBuilder {
		private String charSet = CHAR_SET;
		private String userAgent = "Snet/" + SNET_VERSION;
		private int connectionTimeout = TIME_OUT;
		private int readTimeout = TIME_OUT;
		private boolean useCaches = USE_CACHES;
		private boolean followRedirects = FOLLOW_REDIRECTS;
		private boolean useLocalTest = USE_LOCAL_TEST;

		public SnetConfigBuilder() {
		}

		/**
		 * 设置请求时的User-Agent参数，默认为Snet当前的版本。
		 * 
		 * @param userAgent
		 * @return
		 */
		public SnetConfigBuilder setUserAgent(String userAgent) {
			this.userAgent = userAgent;
			return this;
		}

		/**
		 * 设置连接超时时间。默认为{@code SnetConfig#TIME_OUT}。
		 * 
		 * @param timeoutMillis
		 *            毫秒
		 * @return
		 */
		public SnetConfigBuilder setConnectionTimeout(int timeoutMillis) {

			this.connectionTimeout = timeoutMillis;
			return this;
		}

		/**
		 * 设置读取超时时间。默认为{@code SnetConfig#TIME_OUT}。
		 * 
		 * @param timeoutMillis
		 *            毫秒
		 * @return
		 */
		public SnetConfigBuilder setReadTimeout(int timeoutMillis) {
			this.readTimeout = timeoutMillis;
			return this;
		}

		/**
		 * 设置是否使用cache。默认为{@code SnetConfig#USE_CACHES}。
		 * 
		 * @param useCaches
		 * @return
		 */
		public SnetConfigBuilder setUseCaches(boolean useCaches) {
			this.useCaches = useCaches;
			return this;
		}

		/**
		 * 设置是否支持重定向。默认为{@code SnetConfig#FOLLOW_REDIRECTS}。
		 * 
		 * @param followRedirects
		 * @return
		 */
		public SnetConfigBuilder setFollowRedirects(boolean followRedirects) {
			this.followRedirects = followRedirects;
			return this;
		}

		/**
		 * 设置使用的编码格式。默认值为{@code SnetConfig#CHAR_SET}。
		 * 
		 * @param charSet
		 */
		public SnetConfigBuilder setCharSet(String charSet) {
			this.charSet = charSet;
			return this;
		}

		/**
		 * 设置是否使用本地测试。默认值为{@code SnetConfig#USE_LOCAL_TEST}。
		 * 
		 * @param useLocalTest
		 */
		public void setUseLocalTest(boolean useLocalTest) {
			this.useLocalTest = useLocalTest;
		}
	}
}
